/*
 * Copyright (C) 2020 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.squareup.wire.schema

import okio.Path

/**
 * [ClaimedPaths] tracks generated files' [Path]s. [Schema handlers][SchemaHandler] who generate
 * files are to [claim] each generated file's path. It is an error to generate different [Type]s or
 * [Service]s to the same file and [ClaimedPaths] will throw when generation conflicts happen.
 */
class ClaimedPaths {
  private val paths = mutableMapOf<Path, String>()

  /** Tracks that [type] has been generated to [path]. */
  fun claim(path: Path, type: Type) {
    val errorMessage = type.asErrorMessage()
    val existingEntry = paths[path]
    check(existingEntry == null) {
      "Same file $path is getting generated by different messages:\n" +
        "  ${existingEntry}\n" +
        "  ${type.asErrorMessage()}"
    }
    paths[path] = errorMessage
  }

  /** Tracks that [service] has been generated to [path]. */
  fun claim(path: Path, service: Service) {
    val errorMessage = service.asErrorMessage()
    val existingEntry = paths[path]
    check(existingEntry == null) {
      "Same file $path is getting generated by different services:\n" +
        "  ${existingEntry}\n" +
        "  ${service.asErrorMessage()}"
    }
    paths[path] = errorMessage
  }

  /** Tracks that [extend] has been generated to [path]. */
  fun claim(path: Path, extend: Extend) {
    val errorMessage = extend.asErrorMessage()
    val existingEntry = paths[path]
    check(existingEntry == null) {
      "Same file $path is getting generated for different extends:\n" +
        "  ${existingEntry}\n" +
        "  ${extend.asErrorMessage()}"
    }
    paths[path] = errorMessage
  }

  private fun Extend.asErrorMessage(): String = "${type!!.simpleName}.${fields.joinToString()} at $location"
  private fun Type.asErrorMessage(): String = "${type.simpleName} at $location"
  private fun Service.asErrorMessage(): String = "${type.simpleName} at $location"
}
